package com.tbit.uqbike.quartz;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import com.tbit.uqbike.constant.SubAccountConstant;
import com.tbit.uqbike.enums.AdapayCashType;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.vo.SubAccountWithdrawalLogVO;
import com.tbit.uqbike.object.pojo.vo.SubAccountWithdrawalVO;
import com.tbit.uqbike.webmanager.dao.core.AccountConfigExtDao;
import com.tbit.uqbike.webmanager.dao.core.AdaPayConfigDao;
import com.tbit.uqbike.webmanager.dao.core.SubAccountDao;
import com.tbit.uqbike.webmanager.dao.log.SubAccountLogDao;
import com.tbit.uqbike.webmanager.util.adaPay.AdaPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * 分账定时任务
 *
 * @Author:BUGTian
 * @DATE: 2022/5/24
 */
@Component
@Slf4j
public class SubAccountQuartz {

    @Autowired
    private AdaPayConfigDao adaPayConfigDao;

    @Autowired
    private SubAccountDao subAccountDao;

    @Autowired
    private SubAccountLogDao subAccountLogDao;

    @Autowired
    private AccountConfigExtDao configExtDao;


    /**
     * 定时判断审核状态(每小时执行一次)
     */
    //@Scheduled(cron="0 0 0/1 * * ? ")
    public void updateSubAccountStateQuartz() {
        //查询审核中的分账账户
        List<SubAccount> subAccountList = subAccountDao.selectByState(SubAccountConstant.REVIEW);
        if (subAccountList == null || subAccountList.size() < 1) {
            return;
        }
        //查询所有品牌的汇付配置
        Map<Integer, AdaPayConfig> map = getAdaPayConfigMap();
        for (SubAccount subAccount : subAccountList) {
            AdaPayConfig adaPayConfig = map.get(subAccount.getAccountId());
            if (adaPayConfig == null) {
                //汇付配置不存在
                continue;
            }
            try {
                AdaPayUtil.initConfig(adaPayConfig);
                Map<String, Object> member = AdaPayUtil.queryCorpMember(subAccount, adaPayConfig);
                //审核描述
                Object auditDescObj = member.get("audit_desc");
                if (auditDescObj != null) {
                    String auditDesc = auditDescObj.toString();
                    subAccount.setAuditDesc(auditDesc);
                }
                //审核状态 A-待审核；B-审核失败；C-开户失败；D-开户成功但未创建结算账户；E-开户和创建结算账户成功
                Object auditStateObj = member.get("audit_state");
                if (auditStateObj != null) {
                    String auditState = auditStateObj.toString();
                    switch (auditState) {
                        case "A":
                            subAccount.setState(SubAccountConstant.REVIEW);
                            break;
                        case "B":
                            subAccount.setState(SubAccountConstant.ABNORMAL);
                            break;
                        case "C":
                            subAccount.setState(SubAccountConstant.ABNORMAL);
                            break;
                        case "D":
                            subAccount.setState(SubAccountConstant.ABNORMAL);
                            break;
                        case "E":
                            subAccount.setState(SubAccountConstant.NORMAL);
                            break;
                        default:
                            break;
                    }
                    subAccount.setAuditState(auditState);
                }
                //更新审核状态和账户状态
                subAccountDao.updateAuditState(subAccount);
            } catch (BaseAdaPayException e) {
                //查询出错
                log.error("定时任务分账账户查询出错");
                log.error(e.getMessage(), e);
            } catch (Exception e) {
                //初始化出错
                log.error("定时任务分账配置初始化出错");
                log.error(e.getMessage(), e);
            }
        }
    }

    /**
     * 定时更新分账比例状态
     */
    //@Scheduled(cron="0/10 * * * * ? ")
    /*public void updateSubAccountRatioStateQuartz() {
        //查询未生效的分账比例
        List<SubAccountRatio> subAccountRatioList = subAccountDao.selectRatioByState(SubAccountConstant.UN_ACTIVE);
        long now = System.currentTimeMillis();
        Set<Integer> set = new HashSet<>();
        for (SubAccountRatio subAccountRatio : subAccountRatioList) {
            long time = subAccountRatio.getEffectiveTime().getTime();
            if (time <= now) {
                //分账比例已经到达生效时间的区域
                set.add(subAccountRatio.getAccountId());
            }
        }
        if (set.size() > 0) {
            for (Integer accountId : set) {
                //生效中的设为已过期
                subAccountDao.updateSubAccountRatioState(accountId, SubAccountConstant.ACTIVE, SubAccountConstant.ACTIVE_OVER, new Date());
                //未生效的设置为生效中
                subAccountDao.updateSubAccountRatioState(accountId, SubAccountConstant.UN_ACTIVE, SubAccountConstant.ACTIVE, new Date());
            }
        }
    }*/

    /**
     * 定时查询账户余额
     */
    //@Scheduled(cron="0 0 0/1 * * ? ")
    public void querySubAccountBalanceQuartz() {
        //查询正常状态的分账账户
        List<SubAccount> subAccountList = subAccountDao.selectByState(SubAccountConstant.NORMAL);
        if (subAccountList == null || subAccountList.size() < 1) {
            return;
        }
        //查询所有品牌的汇付配置
        Map<Integer, AdaPayConfig> map = getAdaPayConfigMap();
        for (SubAccount subAccount : subAccountList) {
            AdaPayConfig adaPayConfig = map.get(subAccount.getAccountId());
            if (adaPayConfig == null) {
                //汇付配置不存在
                continue;
            }
            try {
                AdaPayUtil.initConfig(adaPayConfig);
                Integer balance = AdaPayUtil.querySubAccountBalance(subAccount, adaPayConfig);
                //更新账户余额信息
                if (balance != 0) {
                    //余额不为0才更新
                    subAccountDao.updateBalance(subAccount.getSubAccountId(), balance);
                }
            } catch (Exception e) {
            }
        }
    }

    /**
     * 定时查询提现到账状态(两小时一次)
     */
    //@Scheduled(cron="0 0 0/2 * * ? ")
    public void querySubAccountWithdrawalLogStateQuartz() {
        //查询所有提现中的
        List<SubAccountWithdrawalLogVO> list = subAccountLogDao.queryWithdrawalLog(null, null, null, null, null, SubAccountConstant.WITHDRAWAL_ING, null);
        Map<Integer, AdaPayConfig> map = getAdaPayConfigMap();
        for (SubAccountWithdrawalLogVO subAccountWithdrawalLogVO : list) {
            AdaPayConfig adaPayConfig = map.get(subAccountWithdrawalLogVO.getAccountId());
            if (adaPayConfig == null) {
                continue;
            }
            try {
                AdaPayUtil.initConfig(adaPayConfig);
                //查询提现状态
                Integer type = AdaPayUtil.queryWithdrawalState(subAccountWithdrawalLogVO, adaPayConfig);
                if (type != null) {
                    //正常查询返回状态
                    switch (type) {
                        case 1:
                            //提现中
                            break;
                        case 2:
                            //提现成功，更新提现状态
                            subAccountLogDao.updateSubAccountWithdrawalLog(subAccountWithdrawalLogVO.getWithdrawalOrderNO(), SubAccountConstant.WITHDRAWAL_SUCCESS);
                            break;
                        case 3:
                            //提现失败
                            subAccountLogDao.updateSubAccountWithdrawalLog(subAccountWithdrawalLogVO.getWithdrawalOrderNO(), SubAccountConstant.WITHDRAWAL_ERROR);
                            break;
                        default:
                            break;
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
    }

    /**
     * 每天早上八点自动提现
     * 自动提现
     */
    //@Scheduled(cron="0 0 8 1/1 * ? ")
    public void autoWithdrawalQuartz() {
        //实时查询一下用户余额
        querySubAccountBalanceQuartz();
        //查询用户提现列表
        List<SubAccountWithdrawalVO> list = subAccountDao.querySubAccountWithdrawal(null);
        if (list == null || list.size() < 1) {
            return;
        }
        //查询所有品牌的汇付配置
        Map<Integer, AdaPayConfig> map = getAdaPayConfigMap();
        for (SubAccountWithdrawalVO s : list) {
            if (s.getWithdrawalWay() == null || s.getWithdrawalWay() != 1) {
                //如果未配置或提现方式不为自动提现，则跳过
                continue;
            }
            if (s.getReserveMoney() == null) {
                //预留金额如果为空,默认给0
                s.setReserveMoney(0);
            }
            Integer balance = s.getBalance();
            //预留金额转换为分
            Integer reserveMoney = s.getReserveMoney() * 100;
            //可提现金额，单位（分）
            Integer money = balance - reserveMoney;
            if (money > 0) {
                //品牌id
                Integer accountId = s.getAccountId();
                //分账账户id
                Integer subAccountId = s.getSubAccountId();
                //提现请求订单号
                String withdrawalOrderNo = null;
                //分转为元,保留两位小数
                Double moneyYuanD = ((double) money / 100D);
                String moneyYuan = String.format("%.2f", moneyYuanD);
                AdaPayConfig adaPayConfig = map.get(accountId);
                if (adaPayConfig == null) {
                    //汇付配置不存在。取消当前自动提现
                    continue;
                }
                List<AccountConfigExt> configs = configExtDao.selectAccountConfigExtList(accountId, "defaultWithdrawCashType");

                AdapayCashType cashType = ObjectUtil.defaultIfNull(AdapayCashType.of(CollUtil.get(configs, 0).getParamValue()), AdapayCashType.T1);
                try {
                    AdaPayUtil.initConfig(adaPayConfig);
                    SubAccount subAccount = new SubAccount();
                    subAccount.setMemberId(s.getMemberId());
                    withdrawalOrderNo = AdaPayUtil.withdrawal(subAccount, adaPayConfig, moneyYuan, cashType, "自动提现");
                } catch (Exception e) {
                    log.error(e.getMessage(), e);
                    continue;
                }
                if (StringUtils.isEmpty(withdrawalOrderNo)) {
                    continue;
                }
                //修改分账账户余额
                subAccountDao.updateBalance(subAccountId, balance - money);
                //插入提现日志
                SubAccountWithdrawalLog subAccountWithdrawalLog = new SubAccountWithdrawalLog(withdrawalOrderNo, accountId, new Date(), null, "系统自动提现", subAccountId, money, SubAccountConstant.WITHDRAWAL_ING, SubAccountConstant.WITHDRAWAL_TYPE_AUTO, s.getBankCardNumber(), "系统自动提现");
                subAccountLogDao.insertSubAccountWithdrawalLog(subAccountWithdrawalLog);
            }
        }
    }

    /**
     * 自动创建商户账号
     */
    //@Scheduled(cron="0 0 0/3 * * ? ")
    public void autoEntryMerchantsSubAccount() {
        List<AdaPayConfig> adaPayConfigList = adaPayConfigDao.getAll();
        for (AdaPayConfig adaPayConfig : adaPayConfigList) {
            //根据品牌id和adaPay商户下的用户id查询分账账户信息
            SubAccount subAccount = subAccountDao.selectByMemberIdAndAccountId(SubAccountConstant.MERCHANTS_MEMBER_ID, adaPayConfig.getAccountId());
            if (subAccount == null) {
                //自动创建商户账户
                subAccountDao.insert(new SubAccount()
                        .setMemberId(SubAccountConstant.MERCHANTS_MEMBER_ID)
                        .setAccountId(adaPayConfig.getAccountId())
                        .setSubAccountType(SubAccountConstant.MASTER_ACCOUNT)
                        .setBankAccountType(2)
                        .setOpenBank("待补全")
                        .setBankCardNumber("待补全")
                        .setUserName("商户账号")
                        .setCardType("00")
                        .setCardNumber("待补全")
                        .setPhone("待补全")
                        .setNickName("商户账号")
                        .setBalance(0)
                        .setState(SubAccountConstant.NORMAL)
                        .setAddTime(new Date()));
            }
        }
    }

    private Map<Integer, AdaPayConfig> getAdaPayConfigMap() {
        List<AdaPayConfig> adaPayConfigList = adaPayConfigDao.getAll();
        Map<Integer, AdaPayConfig> map = new HashMap<>();
        adaPayConfigList.forEach(adaPayConfig -> map.put(adaPayConfig.getAccountId(), adaPayConfig));
        return map;
    }
}
